package com.cuit;

import com.cuit.enums.RpcErrorMessageEnum;
import com.cuit.exception.RpcException;

import java.util.concurrent.*;
import java.util.function.Function;

public class Test {

    public static void main(String[] args) {
        CompletableFuture<Object> objectCompletableFuture = new CompletableFuture<>();
        new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            objectCompletableFuture.complete(new Object());
        }).start();


        try {
            CompletableFuture<Object> within = within(objectCompletableFuture, 700, TimeUnit.MILLISECONDS);
            System.out.println(within.get());

        }catch (RpcException e) {
            e.printStackTrace();
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    public static <T> CompletableFuture<T> within(CompletableFuture<T> future, long timeout, TimeUnit timeUnit){
        CompletableFuture<T> timeoutAfterFuture = timeoutAfter(timeout, timeUnit);
        return future.applyToEither(timeoutAfterFuture, Function.identity());
    }

    public static <T> CompletableFuture<T> timeoutAfter(long timeout,TimeUnit timeUnit){
        CompletableFuture<T> completableFuture = new CompletableFuture<>();
        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
        scheduledThreadPoolExecutor.schedule(() -> {
            completableFuture.completeExceptionally(new RpcException(RpcErrorMessageEnum.SERVICE_INVOCATION_TIMEOUT));
        }, timeout, timeUnit);
        return completableFuture;
    }
}
